package com.yc.test.token;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yc.common.constant.TokenConstants;
import com.yc.common.core.domain.entity.SysUser;
import com.yc.common.core.domain.model.LoginUser;
import com.yc.common.core.redis.RedisCache;
import com.yc.common.utils.JwtUtil;
import com.yc.framework.web.domain.TokenInfo;
import com.yc.system.mapper.SysUserMapper;
import com.yc.system.service.ISysUserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @Author YanChen
 * @Date 2025/4/19 9:12
 **/
@SpringBootTest
public class AdminToken {

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private RedisCache redisCache;

    @Test
    public void getAdminToken() {

        LambdaQueryWrapper<SysUser> lqw = new LambdaQueryWrapper<>();
        LambdaQueryWrapper<SysUser> eq = lqw.eq(SysUser::getPhonenumber, "13800000000");
        SysUser sysUser = sysUserMapper.selectOne(eq);

        LoginUser loginUser = sysUserService.createLoginUser(sysUser.getId());

        TokenInfo tokenInfo = loginUser.getTokenInfo();

        // 生成随机Token ID - 使用更短的UUID
        String tokenId = UUID.randomUUID().toString().replace("-", "").substring(0, 16);

        // 设置Token到用户
        loginUser.getTokenInfo().setTokenId(tokenId);

        // 创建访问Token
        tokenInfo.setAccessToken(createAccessToken(loginUser));

        // 创建和刷新Token
        tokenInfo.setRefreshToken(createRefreshToken(loginUser));

        cacheLoginUser(loginUser);

        System.out.println("AccessToken:" + loginUser.getTokenInfo().getAccessToken());
        System.out.println("RefreshToken:" + loginUser.getTokenInfo().getRefreshToken());
    }

    private void cacheLoginUser(LoginUser loginUser) {
        String tokenId = loginUser.getTokenInfo().getTokenId();
        Long userId = loginUser.getUser().getId();


        // 存储简化的Token信息到Redis (白名单模式)
        Map<String, Object> accessTokenInfo = new HashMap<>();
        accessTokenInfo.put("userId", userId);
        accessTokenInfo.put("username", loginUser.getUsername());
        accessTokenInfo.put("status", loginUser.getUser().getStatus());
        accessTokenInfo.put("loginTime", System.currentTimeMillis());

        // 主存储 - 验证Access Token使用
        redisCache.setCacheObject(
                TokenConstants.ACCESS_TOKEN_KEY + tokenId,
                accessTokenInfo,
                100,
                TimeUnit.DAYS);

        // 采用Redis Hash存储，节省空间
        String userKey = "user:" + userId;
        redisCache.setCacheHash(userKey, "lastTokenId", tokenId);
        redisCache.setCacheHash(userKey, "lastLoginTime", System.currentTimeMillis());
        redisCache.expire(userKey, 100, TimeUnit.DAYS);

        // 刷新Token白名单 - 使用hash结构节省空间
        String refreshKey = "refresh:" + userId;
        redisCache.setCacheHash(refreshKey, tokenId, System.currentTimeMillis());
        redisCache.expire(refreshKey, 100, TimeUnit.DAYS);
    }

    public String createAccessToken(LoginUser loginUser) {
        // 创建JWT Payload - 只包含关键信息
        Map<String, Object> claims = new HashMap<>();
        claims.put("uid", loginUser.getUser().getId());  // 用户ID
        claims.put("typ", "a");                          // 类型标识
        claims.put("jti", loginUser.getTokenInfo().getTokenId()); // JWT ID

        // 可选添加角色标识，避免频繁查询数据库权限
        if (loginUser.getRoles() != null && !loginUser.getRoles().isEmpty()) {
            claims.put("roles", loginUser.getRoles());
        }

        // 生成JWT
        return JwtUtil.createJWT(
                JSON.toJSONString(claims),
                TimeUnit.DAYS.toMillis(100)
        );
    }

    public String createRefreshToken(LoginUser loginUser) {
        // 创建JWT Payload - 简化载荷
        Map<String, Object> claims = new HashMap<>();
        claims.put("uid", loginUser.getUser().getId());
        claims.put("typ", "r"); // 缩短type为typ和单字符
        claims.put("tid", loginUser.getTokenInfo().getTokenId()); // 缩短token为tid

        // 生成JWT - 缩短刷新令牌
        return JwtUtil.createJWT(
                JSON.toJSONString(claims),
                TimeUnit.DAYS.toMillis(100)
        );
    }
}
